package de.justphil.tcg.tcgserver.rest.resources;

import static de.justphil.tcg.tcgserver.commons.logging.TCGLogging.restLogger;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.annotation.Timed;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.core.TimerContext;

import de.justphil.tcg.tcgserver.commons.config.RestConfig;
import de.justphil.tcg.tcgserver.commons.domain.Deck;
import de.justphil.tcg.tcgserver.commons.domain.User;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.CreateDeck;
import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.commons.management.Application;
import de.justphil.tcg.tcgserver.commons.management.DataManager;
import de.justphil.tcg.tcgserver.rest.db.DeckCreator;
import de.justphil.tcg.tcgserver.rest.db.DeckExtinguisher;
import de.justphil.tcg.tcgserver.rest.resources.base.AbstractResource;
import de.justphil.tcg.tcgserver.rest.validators.DeckValidator;

@Path("/deck")
public class DeckResource extends AbstractResource {
	
	private static final Logger log = restLogger(DeckResource.class);
	
	private DataManager dataManager;
	
	public DeckResource() {
		dataManager = Application.getDataManager();
	}
	
	
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
	public Response createDeck(CreateDeck createDeck, @Context HttpHeaders headers) {
		
		User user = aaa(dataManager, headers.getAcceptableLanguages(), headers.getRequestHeader(RestConfig.REQ_HEADER_AUTHORIZATION));
		
		log.debug("createDeck() ## user '{}' ({}) ## ciIds: {}",
				new Object[] { user.getUsername(), user.getId(), Arrays.toString(createDeck.getCardInstances()) });
		
		// TODO: Remove Metrics stuff
		final Timer validation = Metrics.newTimer(this.getClass(), "DeckValidator", TimeUnit.MILLISECONDS, TimeUnit.SECONDS);
		final Timer creation = Metrics.newTimer(this.getClass(), "DeckCreator", TimeUnit.MILLISECONDS, TimeUnit.SECONDS);
		final TimerContext vCtx = validation.time();
		final TimerContext cCtx = creation.time();
		
		try {
			
			try {
				new DeckValidator().validatePost(dataManager, user, createDeck);
			}
			finally {
				vCtx.stop();
			}
			
			try {
				Deck deck = new DeckCreator().createDeck(Application.getEntityManagerFactory(), dataManager, user, createDeck);
				log.debug("New deck '{}' has id {}.", deck.getName(), deck.getId());
			}
			finally {
				cCtx.stop();
			}
			
			
			return created();
		}
		catch (TCGException e) {
			return err(e.getMessage(), (Status) e.getExtra(), headers.getAcceptableLanguages());
		}
		
	}
	
	@DELETE
	@Path("/{deckId: [0-9]+}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response deleteDeck(@PathParam("deckId") long deckId, @Context HttpHeaders headers) {
		
		log.debug("deleteDeck() ## deckId {}", deckId);
		
		User user = aaa(dataManager, headers.getAcceptableLanguages(), headers.getRequestHeader(RestConfig.REQ_HEADER_AUTHORIZATION));
		
		try {
			new DeckValidator().validateDelete(dataManager, user, deckId);
			
			new DeckExtinguisher().deleteDeck(dataManager, user, deckId);
			
			return ok();
		}
		catch (TCGException e) {
			return err(e.getMessage(), (Status) e.getExtra(), headers.getAcceptableLanguages());
		}
		
	}

}
